package com.albert.funny;




import java.util.Date;

import com.albert.funny.ReverseGeocoderProxy.ReverseGeocoderProxyListener;

import android.app.Activity;
import android.app.AlertDialog;
import android.location.Location;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.provider.Settings;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.res.Configuration;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;

public class GPSRecorderActivity extends Activity implements View.OnClickListener, ReverseGeocoderProxyListener 
{
    protected static final long VALID_TIME_DURATION = 180000;
    protected static final int FLAG_LOCATION_NONE = 0;
    protected static final int FLAG_LOCATION_COASE = 1;
    protected static final int FLAG_LOCATION_FINE = 2;
    
    private TextView latituteField;
    private TextView longitudeField;
    private TextView altitudeField;
    private TextView dateField;
    private TextView speedField;
    private AutoCompleteTextView inputField;
//    private CurrentLocationManager currentlocationManager;
   // private GeocoderProxy proxy;
    private String provider;
    private boolean isShowGPSDisabledDlg;
    private Button recordButton;
    private TextView gpsFlagView;
    private TextView accuracyField;
    private Location lastLocation;
    private IRemoteLocationTrackService remoteLocationService;
    private LocationServiceListener locationServiceListener;
    private ServiceConnection  serviceConnection ;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        dateField = (TextView)findViewById(R.id.dateTime);
        latituteField = (TextView) findViewById(R.id.latTextView);
        longitudeField = (TextView) findViewById(R.id.longTextView);
        altitudeField = (TextView)findViewById(R.id.altitTextview);
        accuracyField = (TextView)findViewById(R.id.accuracyTextview);
        recordButton = (Button)findViewById(R.id.recordbutton);
        gpsFlagView = (TextView)findViewById(R.id.gpsflag);
        inputField = (AutoCompleteTextView)findViewById(R.id.inputSpName);
        speedField = (TextView)findViewById(R.id.speedTextview);
        Button reverseGeoCoderButton = (Button)findViewById(R.id.reversegeocodeButton);
        reverseGeoCoderButton.setOnClickListener(this);
        recordButton.setOnClickListener(this);
        String[] items = getResources().getStringArray(R.array.defaultPoilist);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this.getApplicationContext(),
                android.R.layout.simple_dropdown_item_1line, items);
        inputField.setAdapter(adapter);
        inputField.setThreshold(0);
        this.bindToService();
    }

    /* Request updates at startup */
    @Override
    protected void onResume() {
        super.onResume();
        resetUpdateUI();
    }

    private void bindToService()
    {
        serviceConnection = new ServiceConnection()
        {

            @Override
            public void onServiceConnected(ComponentName name, IBinder service)
            {
                // TODO Auto-generated method stub
                locationServiceListener = new LocationServiceListener();
                remoteLocationService = IRemoteLocationTrackService.Stub.asInterface(service);
                try
                {
                    remoteLocationService.registerCallback(locationServiceListener);
                    remoteLocationService.startTracking();
                } catch (RemoteException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }

            @Override
            public void onServiceDisconnected(ComponentName name)
            {
                if(remoteLocationService != null)
                {
                    try
                    {
                        remoteLocationService.unregisterCallback(locationServiceListener);
                        remoteLocationService = null;
                    } catch (RemoteException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                
            }
            
        };
        this.startService(new Intent(this.getApplicationContext(), CurrentLocationTrackingService.class));
        this.bindService(new Intent(this.getApplicationContext(), CurrentLocationTrackingService.class), serviceConnection, BIND_AUTO_CREATE);
        
    }

    public boolean onCreateOptionsMenu (Menu menu)
    {
        MenuItem item = menu.add(R.string.stop_service_label);
        item.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            @Override
            public boolean onMenuItemClick(MenuItem item)
            {
                if(remoteLocationService != null && serviceConnection != null)
                {
                    try
                    {
                        remoteLocationService.stopTracking();
                        
                        unBindService();
                        Intent intent = new Intent();
                        intent.setAction(IRemoteLocationTrackService.class.getName());
                        stopService(intent);
                        resetUpdateUI();
                    } catch (RemoteException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                return true;
            }
        });
        
        MenuItem item2 = menu.add(R.string.start_service_label);
        item2.setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener()
        {
            @Override
            public boolean onMenuItemClick(MenuItem item)
            {
                if(remoteLocationService != null)
                {
                    try
                    {
                        remoteLocationService.startTracking();
                    } catch (RemoteException e)
                    {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                else
                {
                    bindToService();
                }
                return true;
            }
        });
        return super.onCreateOptionsMenu(menu);
    }
    
//    public void onConfigurationChanged (Configuration newConfig)
//    {
//        
//    }

    public void onStop()
    {
        resetUpdateUI();
        this.lastLocation = null;
        super.onPause();
        
    }
    
    public void onDestroy()
    {
        this.bindToService();
        super.onDestroy();
    }
    
    private void unBindService()
    {
        if(serviceConnection != null)
        {
            this.unbindService(serviceConnection);
            serviceConnection = null;
        }
    }

    private void showGotoSettingAlert(final String provider)
    {
      if (!isShowGPSDisabledDlg)
      {
          LayoutInflater layoutInflater = this.getLayoutInflater();
          ViewGroup viewGroup = (ViewGroup) layoutInflater.inflate(R.layout.gpsdisabledialog, null);
          Button okButton = (Button) viewGroup.findViewById(R.id.gotoLocationSetting);
          AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);
          alertDialogBuilder.setView(viewGroup);
          final AlertDialog alertDialog = alertDialogBuilder.create();
          okButton.setOnClickListener(new View.OnClickListener()
          {

              @Override
              public void onClick(View v)
              {
                  if(v.getId() == R.id.gotoLocationSetting)
                  {
                      if(LocationManager.GPS_PROVIDER.equalsIgnoreCase(provider))
                      {
                          gotoGPSSettingScreen();
                      }
                      else
                      {
                          gotoNetworkSettingScreen();
                      }
                      alertDialog.dismiss();
                  }

              }
          });
          
          alertDialog.show();
          isShowGPSDisabledDlg = true;

      }
    }
    private void gotoNetworkSettingScreen()
    {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_NETWORK_OPERATOR_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }
    
    private void gotoGPSSettingScreen()
    {
        Intent intent = new Intent();
        intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        
    }

    @Override
    public void onClick(View v)
    {
        if (v.getId() == R.id.recordbutton)
        {
            if (isCanRecording())
            {
                recordGPS();

            }
            else
            {
                Toast.makeText(this, R.string.save_gps_fail, 2000).show();
            }
        }
        else if(v.getId() == R.id.reversegeocodeButton)
        {
           reverseGeoCode();
        }
    }

    private void reverseGeoCode()
    {
        if(lastLocation != null)
        {
            ReverseGeocoderProxy proxy = new ReverseGeocoderProxy(this);
            proxy.setGeocoderListener(this);
            proxy.execute(lastLocation); 
        }
        else
        {
            Toast.makeText(this, R.string.invalid_gps_location, 2000).show();
        }
    }

    private void recordGPS()
    {
        String placeName = this.inputField.getText().toString();
        try
        {
            this.remoteLocationService.recordLocation(placeName);
        } catch (RemoteException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }

    private boolean isCanRecording()
    {
        if(inputField.getText().length() > 0 && lastLocation != null)
        {
            return true;
        }
        else
            return false;
    }

    private void updateFlag(Location location)
    {
        if (location != null) {
            if(LocationValidationUtil.isFineLocation(location))
            {
                updateFlag(FLAG_LOCATION_FINE);
            }
            else
            {
                updateFlag(FLAG_LOCATION_COASE);
            }
           
        }
        else
        {
            updateFlag(FLAG_LOCATION_NONE);
        }
    }
    
    private void updateFlag(int flag)
    {
        boolean canSend = false;
        int recordButtonTextColor = Color.GRAY;
        int gpsFlagBgColor = Color.RED;
        int gpsFlagTextColor = Color.WHITE;
        int resId = R.string.gpsinvalidString;
        switch (flag)
        {
            case FLAG_LOCATION_FINE:
            {
                canSend = true;
                recordButtonTextColor = Color.BLACK;
                gpsFlagTextColor = Color.BLACK;
                gpsFlagBgColor = Color.GREEN;
                resId = R.string.gpsvalidstring;
                break;
            }
            case FLAG_LOCATION_COASE:
            {
                canSend = true;
                recordButtonTextColor = Color.BLACK;
                gpsFlagTextColor = Color.BLACK;
                gpsFlagBgColor = Color.YELLOW;
                resId = R.string.gpsfuzzyString;
                break;
            }

        }
        gpsFlagView.setBackgroundColor(gpsFlagBgColor);
        gpsFlagView.setText(resId);
        gpsFlagView.setTextColor(gpsFlagTextColor);
        recordButton.setTextColor(recordButtonTextColor);
        recordButton.setClickable(canSend);
        
    }

    private void updateLocationInfo(Location location)
    {
        if (location != null)
        {
            long time = location.getTime();
            Date data = new Date();
            data.setTime(time);
            dateField.setText(data.toLocaleString());
            double lat = (location.getLatitude());
            double lng = (location.getLongitude());
            double alti = location.getAltitude();
            double acc = location.getAccuracy();
            double speed = location.getSpeed();
            latituteField.setText(String.valueOf(lat));
            longitudeField.setText(String.valueOf(lng));
            altitudeField.setText(String.valueOf(alti));
            accuracyField.setText(String.valueOf(acc));
            speedField.setText(String.valueOf(speed));
        }
        else
        {
            dateField.setText(R.string.timeString);
           
            latituteField.setText(R.string.gpsinvalidString);
            longitudeField.setText(R.string.gpsinvalidString);
            altitudeField.setText(R.string.gpsinvalidString);
            accuracyField.setText(R.string.gpsinvalidString);
            speedField.setText(R.string.gpsinvalidString);
        }
    }

    @Override
    public void reverseGeoCoderFinished(int status, String address)
    {
        if(status == ReverseGeocoderProxy.SUCCESS)
        {
           
            this.inputField.setText(address);
        }
        else
        {
            Toast.makeText(this, R.string.geocode_fail, 2000).show();
        }
        
    }
    private class LocationServiceListener extends IRemoteLocationTrackServiceCallback.Stub
    {

        @Override
        public void locationChanged(int status, Location location) throws RemoteException
        {
            if (location != null)
            {
                lastLocation = location;
            }
            switch (status)
            {
                case CurrentLocationManager.FLAG_LOCATION_DEVICE_OFF:
                {
                    showGotoSettingAlert(LocationManager.GPS_PROVIDER);
                    break;
                }
                case CurrentLocationManager.FLAG_NEW_LOCATION_ARRIVAL:
                {
                    updateView(location);
                    
                    break;
                }
                case CurrentLocationManager.FLAG_LOCATION_NO_LOCATION:
                {
                    resetUpdateUI();
                    break;
                }
                case CurrentLocationManager.FLAG_LOCATION_REQUIRING:
                {
                    resetUpdateUI();
                    break;
                }
            }
        }
        
    }
    
    public void resetUpdateUI()
    {
        updateFlag(null);
        updateLocationInfo(null);
    }
    
    protected void updateView(final Location location)
    {
        this.runOnUiThread(new Runnable()
        {
            @Override
            public void run()
            {
                updateFlag(location);
                updateLocationInfo(location);
                
            }
        });
    }
}

